#include "LinkControl.h"
#include "utils/_KitharaSmp.h"
#include "kernel/shared-memory.h"

#include <vector>
#include <iostream>


const char* customer_number = "070075";
constexpr int buffer_size = 1024;

int64 GetCurrentTime(){
    int64 time{};
    KS_getClock(&time, KS_CLOCK_MEASURE_HIGHEST);
    return time;
}

int main(int argc, char *argv[]) {
    outputTxt("**** kithara test demo ****");
    KSError ksError;
    // 打开驱动
    ksError = KS_openDriver(customer_number);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_openDriver", "Failed to open driver!");
        return -1;
    }
        auto start_time = GetCurrentTime();
    std::vector<int> myVector;
    for(int i = 0; i < 1000000; i++){
        myVector.push_back(i);
    }
    auto end_time = GetCurrentTime();
    int64 machine_time = end_time - start_time;
    KS_convertClock(&machine_time, KS_CLOCK_MEASURE_HIGHEST,
                    KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS);
     KS_convertClock(&start_time, KS_CLOCK_MEASURE_HIGHEST,
                    KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS);
    KS_convertClock(&end_time, KS_CLOCK_MEASURE_HIGHEST,
                    KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS);

    std::cout << "user level time: " << machine_time <<
    " * 100ns " << std::endl;


    // 创建共享内存
    KSHandle shared_memory_handle{};
    ksError = KS_createSharedMemEx(
        &shared_memory_handle,
        "",
        sizeof(SharedData),
        KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_createSharedMemEx", "Failed to create shared memory!");
        return -1;
    }
    // 获取共享内存指针
    SharedData* shared_memory_app{};
    ksError = KS_getSharedMemEx(
        shared_memory_handle,
        (void**)&shared_memory_app,
        KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_getSharedMemEx", "Failed to get shared memory!");
        return -1;
    }
    shared_memory_app->number = 666;
    // 获取系统信息
    KSSystemInformation system_info{};
    system_info.structSize = sizeof(KSSystemInformation);
    ksError = KS_getSystemInformation(
        &system_info,
        KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_getSystemInformation", "Failed to get system information!");
        KS_closeDriver();
        return -1;
    }
    outputTxt("**** system information ****");
    outputDec(system_info.numberOfCPUs, "cpu numbers: ");
    outputDec(system_info.numberOfSharedCPUs, "shared cpu numbers: ");
    int fallBackCpu = system_info.numberOfSharedCPUs;
    int cpu = inputDec("Which CPU shall be used ", fallBackCpu);
    if (cpu < system_info.numberOfSharedCPUs || cpu >= system_info.numberOfCPUs) {
        outputDec(cpu, "Sorry, CPU ", " is not available. ", false);
        outputDec(fallBackCpu, "Using CPU ", " instead.");
        cpu = fallBackCpu;
    }
    ksError = KS_setTargetProcessor(cpu, KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_setTargetProcessor", "Failed to set target processor!");
        KS_closeDriver();
        return -1;
    }
    // 创建消息管道
    outputTxt("create message pipe");
    ksError = KS_createPipe(
        &shared_memory_app->hPipe,
        "message_pipe",
        1000,
        buffer_size * sizeof(char),
        KS_INVALID_HANDLE,
        KSF_MESSAGE_PIPE);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_createPipe", "Failed to create message pipe!");
        KS_closeDriver();
        return -1;
    }
    // 创建等待事件
    ksError = KS_createEvent(
            &shared_memory_app->hWaitEvent,
            "TimerWaitEvent",
            KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_createEvent", "Failed to create event!");
        KS_closeDriver();
        return -1;
    }
    // 加载内核 kernel-class.dll
    ksError = KS_loadKernel(
        &shared_memory_app->hKernel_class,
        "kernel-class.dll",
        NULL,
        NULL,
        KSF_KERNEL_EXEC);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_loadKernel", "Failed to load kernel kernel-class!");
        KS_closeDriver();
        return -1;
    }
    outputTxt("kernel-dll loaded!");
    // 加载内核 kernel-dll.dll
    ksError = KS_loadKernel(
        &shared_memory_app->hKernel_dll,
        "kernel-dll.dll",
        NULL,
        NULL,
        KSF_KERNEL_EXEC);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_loadKernel", "Failed to load kernel kernel-dll!");
        KS_closeDriver();
        return -1;
    }
    // 执行内核回调
    ksError = KS_execKernelFunctionEx(
        shared_memory_app->hKernel_dll,
        "_initFunction",
        shared_memory_handle,
        KS_INVALID_HANDLE,
        KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_execKernelFunctionEx", "Failed to execute kernel function!");
        KS_closeDriver();
        return -1;
    }
    outputTxt("kernel function \"_initFunction\" executed!");
    outputDec(shared_memory_app->number, "number: ");
    waitTime(500 * ms);
    // 循环读取管道消息
    int length{};
    char read_buffer[buffer_size]{};
    while(true) {
        // 等待事件
        ksError = KS_waitForEvent(shared_memory_app->hWaitEvent, KSF_NO_FLAGS, 3 * s);
        if (ksError != KS_OK) {
            outputErr(ksError, "KS_waitForEvent", "Failed to wait for event!");
            break;
        }
        // 读取管道消息
        while (KS_OK == KS_getPipe(
            shared_memory_app->hPipe,
            read_buffer,
            buffer_size,
            &length,
            KSF_NO_FLAGS)) {
            read_buffer[length] = '\0';
            outputTxt(read_buffer, false);
        }
        if (_kbhit()) {
            const char key = _getch();
            if (key == 'q' || key == 'Q') {
                break;
            }
        }
    }
    ksError = KS_stopTimer(shared_memory_app->hTimer);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_stopTimer", "Failed to stop timer!");
    }
    waitTime(500 * ms);
    // 执行内核回调
    ksError = KS_execKernelFunctionEx(
        shared_memory_app->hKernel_dll,
        "_exitFunction",
        shared_memory_handle,
        KS_INVALID_HANDLE,
        KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_execKernelFunctionEx", "Failed to execute kernel function!");
        KS_closeDriver();
        return -1;
    }
    outputTxt("kernel function \"_exitFunction\" executed!");
    outputDec(shared_memory_app->number, "number: ");
    // 释放资源
    ksError = KS_freeKernel(
        shared_memory_app->hKernel_dll);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_freeKernel", "Failed to free kernel kernel-dll!");
    }
    // 释放资源
    ksError = KS_freeKernel(
        shared_memory_app->hKernel_class);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_freeKernel", "Failed to free kernel kernel-class!");
    }
    // 关闭消息管道
    ksError = KS_removePipe(shared_memory_app->hPipe);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_removePipe", "Failed to remove pipe!");
    }
    // 关闭等待事件
    ksError = KS_closeEvent(shared_memory_app->hWaitEvent);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_closeEvent", "Failed to close event!");
    }

    // 释放共享内存
    ksError = KS_freeSharedMemEx(
        shared_memory_handle,
        KSF_NO_FLAGS);
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_freeSharedMemEx", "Failed to free shared memory!");
    }
    // 关闭驱动
    ksError = KS_closeDriver();
    if (ksError != KS_OK) {
        outputErr(ksError, "KS_closeDriver", "Failed to close driver!");
    }
    waitTime(500 * ms);
    outputTxt(" ");
    outputTxt("End of program 'test demo'.");
    return 0;
}